package com.caio.svn;


import static com.caio.svn.Configuracoes.*;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.enterprise.context.SessionScoped;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.validator.ValidatorException;
import javax.inject.Inject;
import javax.script.ScriptException;

import org.apache.log4j.helpers.FileWatchdog;
import org.hibernate.annotations.Index;

import antlr.Utils;

import com.caio.svn.excption.ScriptInvalidoExcption;
import com.caioweb.osa.mb.GeraScriptBean;
import com.caioweb.osa.modelo.Arquivo;
import com.caioweb.osa.modelo.Historico;
import com.mysql.jdbc.Util;


public class GeraScriptLinux implements Serializable{
	private Historico historico;
	private Process process;
	private Runtime run;
	private String revisaoAtual;
	private String url;
	private List<String> listaDados;
	private List<String> listaEstrutura;
	private String diretorioSelecionado;
	private String diretorioCriacao;
	@Inject
	private GeraScriptBean bean;
	

	
	public GeraScriptLinux(Historico historico) throws IOException, InterruptedException{
		this.historico = historico;
		this.url = historico.getAmbiente().getBranch().getUrl();
		this.run = Runtime.getRuntime();
	}
	
	
	public synchronized  boolean executaCriacao(GeraScriptBean bean) throws IOException, InterruptedException{
		this.bean = bean;
		
		try {
			this.bean.setLog("[Iniciando geração de Script] <br/><br/>");
			ultimaRevisao();
			verificarArquivosDifentes();
			validaArquivos();
			chekoutArquivos();
			criaArquivo();
			escreveDados();
			escreveEstrutura();
			limpaLogs();
		} catch (ScriptInvalidoExcption e) {
			return false;
		}

		return true;
	}
	
	public void limpaLogs(){
		executa(rm -rf )
	}
	
	// verifica o numero da ultima revisão (HEAD), há nescessidade desse metodo pois é preciso
	// gravar o numero do head
	public synchronized void ultimaRevisao() throws IOException, InterruptedException, ScriptInvalidoExcption{
		String nomeArquivo = UtilSvn.nomeAleatorio();
		executa(SH_HEAD + " " + url +" " +  DIR_DEPLOY_TEMP+ nomeArquivo + ".txt");
	
	    revisaoAtual = UtilSvn.lerArquivo(DIR_DEPLOY_TEMP + nomeArquivo +".txt");

		historico.setRevisaoFinal(new Integer(revisaoAtual));
		this.bean.setLog("-Revisão do cliente : " + historico.getRevisaoInicial()+" <br/>");
		this.bean.setLog("-Revisão atual SVN (HEAD): " + historico.getRevisaoFinal() + "<br/><br/> ");

       return;
		
	}
	
	
	//vai no svn e verifica os arquivos que estão dentro de um intervalo de commit, ou seja
	// os arquivos que deveram ser enviados para o cliente e preenche um array list com os mesmos 
	public synchronized void  verificarArquivosDifentes() throws IOException, InterruptedException, ScriptInvalidoExcption{
		String nomeArquivoDados = UtilSvn.nomeAleatorio();
		String nomeArquivoEstrutura =  UtilSvn.nomeAleatorio();
	    UtilSvn.criaDiretorio(DIR_DEPLOY + historico.getAmbiente().getCliente().getSigla());
	    VerificaDados(nomeArquivoDados);
	    VerificaEstrutura(nomeArquivoEstrutura);
	 
	}
	
	public void VerificaDados(String nomeArquivoDados) throws IOException, InterruptedException, ScriptInvalidoExcption{
	    this.bean.setLog("* Verificando arquivos de dados ....  \n  <br>");
	    executa(SH_DIFF + " "  + historico.getRevisaoInicial() +" "+ historico.getRevisaoFinal() + 
	    					 " "+url+ " "+historico.getAmbiente().getTipoBancoDeDados().getNomenclatura()
	    					 +" "+ NM_DIR_DADOS  +" "+ DIR_DEPLOY+ getSigla()+ "/" +nomeArquivoDados+".txt");
	    this.listaDados = lerTxt(DIR_DEPLOY+ getSigla()+ "/" +nomeArquivoDados+".txt");
	    this.bean.setLog("* Modificações encontradas em script de Dados : "+listaDados.size()+" \n  <br><br>");
	}
	public void VerificaEstrutura(String nomeArquivoEstrutura) throws IOException, InterruptedException, ScriptInvalidoExcption{
	    this.bean.setLog("* Verificando arquivos de Estrutura ...  \n  <br>");
	    executa(SH_DIFF + " "  + historico.getRevisaoInicial() +" "+ historico.getRevisaoFinal() + 
	    					 " "+url+ " "+historico.getAmbiente().getTipoBancoDeDados().getNomenclatura()
	    					 +" "+ NM_DIR_ESTRUTURA  +" "+ DIR_DEPLOY+ getSigla()+ "/" +nomeArquivoEstrutura+".txt");
	    this.listaEstrutura = lerTxt(DIR_DEPLOY+ getSigla()+ "/" +nomeArquivoEstrutura+".txt");
	    this.bean.setLog("* Modificações encontradas em script de Estrutura : "+listaEstrutura.size()+" \n  <br><br>");
	}
	
	
	// faz download de todos os arquivos do repositório, separa em outra pasta apenas os arquivos que
	//  que estão no intervalo de commit
	public void chekoutArquivos() throws IOException, InterruptedException{
		this.bean.setLog("* Fazendo checkout de arquivos ...  \n  <br>");
		String diretorioComTodos = DIR_DEPLOY+ getSigla()+"/"+UtilSvn.nomeAleatorio();
		executa(SH_EXPORT + " " + url + " " +diretorioComTodos );
		this.diretorioSelecionado = DIR_DEPLOY+ getSigla()+"/"+UtilSvn.nomeAleatorio();
		UtilSvn.criaDiretorio(diretorioSelecionado);
		UtilSvn.criaDiretorio(diretorioSelecionado + "/"+ NM_DIR_DADOS);
		UtilSvn.criaDiretorio(diretorioSelecionado + "/"+ NM_DIR_ESTRUTURA);
		
		
		//MENSAGEM NA TELA
		this.bean.setLog("* movendo arquivos para o diretorio :  \n  <br>");
		this.bean.setLog(diretorioSelecionado + "<br/><br/>");
		
		List<String> listaTemp = new ArrayList<String>();
		for(String arquivo:  listaDados){
			if(arquivo.contains(NM_DADOS) || arquivo.contains(getSigla().toUpperCase()) || arquivo.contains(getSigla().toLowerCase())){
				listaTemp.add(arquivo);
				executa(SH_MOVE + " "+ diretorioComTodos+ "/" + arquivo + " "+diretorioSelecionado+ "/" + NM_DIR_DADOS);
			}
			
		}
		this.listaDados = listaTemp;
		listaTemp = new ArrayList<String>();
		for(String arquivo:  listaEstrutura){
			if(arquivo.contains(NM_ESTRUTURA) || arquivo.contains(getSigla().toUpperCase()) || arquivo.contains(getSigla().toLowerCase())){
				listaTemp.add(arquivo);
			 executa(SH_MOVE + " "+ diretorioComTodos+ "/" + arquivo + " "+diretorioSelecionado + "/" + NM_DIR_ESTRUTURA);
			}	
		}
		this.listaEstrutura = listaTemp;
		listaTemp = new ArrayList<String>();
		listaTemp.addAll(listaDados);
		listaTemp.addAll(listaEstrutura);
		
		List<Arquivo> arquivos = new ArrayList<Arquivo>();
		
		Collections.sort(listaTemp);
		for(String arquivo :listaTemp){
			Arquivo a = new Arquivo();
			a.setNome(arquivo);
			a.setHistorico(bean.getHistorico());
			arquivos.add(a);
		}
		
		bean.getHistorico().setArquivos(arquivos);
	}
	
	// separa os arquivos de dados , estrutura , imediatos
//	public void separaArquivos() throws IOException, InterruptedException{
//		arquivoDeDados();
//		arquivoDeEstrutura();
//	}
	
	public void criaArquivo() throws IOException{
		this.diretorioCriacao = DIR_DOCUMENTOS + getSigla() +"/" + UtilSvn.getDate(System.currentTimeMillis()) +"/";
		UtilSvn.criaDiretorio(diretorioCriacao);
		this.bean.getHistorico().setArquivo(diretorioCriacao);
		this.bean.setLog(" * Criando arquivo de dados e estrutura para o diretório: <br/> ");
		this.bean.setLog("    "+diretorioCriacao +"<br/><br/>");
		UtilSvn.criaArquivo(diretorioCriacao + TXT_DADOS);
		UtilSvn.criaArquivo(diretorioCriacao + TXT_ESTRUTURA);
		
	}
	
	public void escreveDados(){
		for(String arquivo: listaDados){
			lerEscreveArquivo(diretorioSelecionado + "/" +arquivo,  diretorioCriacao + TXT_DADOS,arquivo) ;
		}
		
	}
	public void escreveEstrutura(){
		// estrutura de ser ordenado pelo nome
		Collections.sort(listaEstrutura);
		for(String arquivo: listaEstrutura){
			lerEscreveArquivo(diretorioSelecionado + "/" +arquivo,  diretorioCriacao + TXT_ESTRUTURA,arquivo) ;
		}
		
	}
	
	// faz uma lista com todos os arquivos de dados
//	public void arquivoDeDados() throws IOException, InterruptedException{
//		executa(SH_SEPARA + " " + diretorioSelecionado + " "+ NM_DADOS+  " "+diretorioSelecionado+"/"+ TXT_DADOS);
//		this.listaDados = lerTxt(diretorioSelecionado + "/"+ TXT_DADOS);
//	}
//	// faz uma lista com todos os arquivos de estrutura
//	public void arquivoDeEstrutura() throws IOException, InterruptedException{
//		executa(SH_SEPARA + " " + diretorioSelecionado + " "+ NM_ESTRUTURA + " "+ diretorioSelecionado+"/" + TXT_ESTRUTURA);
//		this.listaEstrutura = lerTxt(diretorioSelecionado + "/"+TXT_ESTRUTURA);
//	}
	
	public List<String> lerTxt(String url) throws ScriptInvalidoExcption{
		List<String> list = new ArrayList<String>();
	    try {
	        FileReader file= new FileReader(url);
	        BufferedReader buf = new BufferedReader(file);
	   
	        String linha = buf.readLine();
	        while (linha != null) {
	          System.out.printf("%s\n", linha);
	          

	          list.add(linha);
	          linha = buf.readLine(); // lê da segunda até a última linha
	        }
	   
	        file.close();
	      } catch (IOException e) {
	   
	          System.err.printf("Erro na abertura do arquivo: %s.\n",
	            e.getMessage());
	      }
	    
	    
	    //verificar se algum arquivo que tinha espaco ja foi renomeado
	    for(String arquivo : list){
	    	if(arquivo.contains(" ")){
	    		if(!list.contains(arquivo.replace(" ", ""))){
	    			UtilSvn.mensagem("O arquivo " + arquivo + " , possue espacos em branco na nomenclatura, favor corrigir ",true);
	    			throw new ScriptInvalidoExcption();
	    		}
	    	
	    	}
	    }
	    
	    return list;
	}
	
	public void lerEscreveArquivo(String url,String arquivo,String arquivoRepositorio){
		try {
			// ler arquivo
			FileReader fileReader = new FileReader(url);
			BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(url), "ISO-8859-1"));
			//esqueve arquivo
		    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(arquivo,true), "UTF-8"));  
		    bw.write("-- "+historico.getAmbiente().getBranch().getNome() + " " + historico.getAmbiente().getTipoAmbienteCliente().getTipo());
		    bw.newLine();
		    bw.write("-- " +arquivoRepositorio);
		    bw.newLine();
			String linha = bufferedReader.readLine();
			while(linha != null){
				bw.write(linha);
			//	this.bean.setLog(linha);
				bw.newLine();
			linha = bufferedReader.readLine();
			}
			
			bufferedReader.close();
			bw.close();
			
		} catch (Exception e) {
			System.out.println("ERRO AO LER OU ESCREVER AQUIVO " +url);
		}
	  
	}
	
	
	public void executa(String command) throws IOException, InterruptedException{
		System.out.println();
		System.out.println(command);
		process = run.exec(command);
		process.waitFor();
		
	}
	
	public String getSigla(){
		return historico.getAmbiente().getCliente().getSigla();
	}
	
	public void validaArquivos() throws ScriptInvalidoExcption{
		boolean valida = (listaDados.isEmpty() && listaEstrutura.isEmpty());
		if(UtilSvn.mensagem("Nao exsiste script para o cliente "+getSigla(),valida)){
			throw new ScriptInvalidoExcption();
		}
		
	}
		
}
	
	
	
	

